package work.mediway.mdm.biz.dto.dict;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.google.gson.annotations.SerializedName;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import work.mediway.mdm.core.constant.MdmConstant;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/4/16
 */
@Data
@ApiModel
public class DictGeneralDTO {

    /**
     * Request : {"Data":[{"CTS_CodesystemCode":"代码表类型","code":"code","sourcerowid":"源系统唯一码","release":"发布状态","CTS_CreatTime":"创建时间","description":"description","UpdateDate":"时间戳日期","CTS_EndDate":"有效结束日期","CTS_OriginalDesc":"原描述","CTS_UpdateTime":"最后更新时间","CTS_Code":"代码","groupbusiness":"集团业务域","businessrowid":"业务域内rowid","CTS_UpdateUserCode":"最后更新人编码","BusinessFieldCode":"业务域","grouprowid":"集团全局","version":"版本","CTS_HosCode":"医院代码","CTS_Remarks":"备注","CTS_StartDate":"有效开始日期","CTS_CreatDate":"创建日期","CTS_UpdateDate":"最后更新日期","system":"系统代码","UpdateTime":"时间戳时间","CTS_Desc":"描述","CTS_OriginalCode":"原代码","CTS_Status":"状态"}],"TableCode":"CT_Sex"}
     */

    @Setter
    @Getter
    @SerializedName(value = "Request")
    private RequestBean request;

    @ToString
    public static class RequestBean {

        @Setter
        @SerializedName(value = "TableCode")
        private String tableCode;

        @Setter
        @Getter
        @SerializedName(value = "Data")
        private List<Map<String, Object>> data;

        public String getTableCode() {
            return StrUtil.removePrefix(tableCode, MdmConstant.SCHEMA_NAME_);
        }
    }

    public static DictGeneralDTO build(Object data, Class<?> clazz) {
        DictGeneralDTO dictGeneralDTO = new DictGeneralDTO();
        RequestBean requestBean = new RequestBean();
        requestBean.setTableCode(clazz.getAnnotation(TableName.class).value());
        requestBean.setData(CollUtil.newArrayList(getDatabaseMap(clazz, BeanUtil.beanToMap(data))));
        dictGeneralDTO.setRequest(requestBean);
        return dictGeneralDTO;
    }

    public static DictGeneralDTO build(List<Object> data, Class<?> clazz) {
        DictGeneralDTO dictGeneralDTO = new DictGeneralDTO();
        RequestBean requestBean = new RequestBean();
        requestBean.setTableCode(clazz.getAnnotation(TableName.class).value());
        List<Map<String, Object>> objects = CollUtil.newArrayList();
        for (Object datum : data) {
            objects.add(getDatabaseMap(clazz, BeanUtil.beanToMap(datum)));
        }
        requestBean.setData(objects);
        dictGeneralDTO.setRequest(requestBean);
        return dictGeneralDTO;
    }

    /**
     * 获取对象中数据
     *
     * @param clazz class
     * @param map   数据集合
     * @param <T>   领域泛型
     * @return 数据库字段map
     */
    private static <T> Map<String, Object> getDatabaseMap(Class<T> clazz, Map<String, Object> map) {
        Map<String, Object> result = MapUtil.newHashMap();
        // 获取对象的所有字段
        Field[] fields = ReflectUtil.getFields(clazz);
        for (Field field : fields) {
            TableField tableField = field.getAnnotation(TableField.class);
            TableId tableId = field.getAnnotation(TableId.class);
            if (ObjectUtil.isNotEmpty(tableField)) {
                if (tableField.exist()) {
                    if (ObjectUtil.isNotEmpty(map.get(field.getName()))) {
                        result.put(tableField.value(), map.get(field.getName()));
                    } else {
                        result.put(tableField.value(), map.get(tableField.value()));
                    }
                }
            } else if (ObjectUtil.isNotEmpty(tableId)) {
                if (ObjectUtil.isNotEmpty(map.get(field.getName()))) {
                    result.put(tableId.value(), map.get(field.getName()));
                } else {
                    result.put(tableId.value(), map.get(tableId.value()));
                }
            }
        }
        return result;
    }
}
